package com.erpanderp.wam.adm.view;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import org.primefaces.component.datatable.DataTable;

import com.erpanderp.wam.adm.model.entity.Resource;
import com.erpanderp.wam.adm.model.entity.Role;
import com.erpanderp.wam.adm.model.entity.RoleService;
import com.erpanderp.wam.adm.model.entity.RoleServiceGroup;
import com.erpanderp.wam.adm.model.entity.Service;
import com.erpanderp.wam.adm.model.entity.ServiceGroup;
import com.erpanderp.wam.adm.model.entity.ServiceResource;
import com.erpanderp.wam.adm.model.service.RoleDAO;
import com.erpanderp.wam.adm.model.service.ServiceDAO;
import com.erpanderp.wam.adm.model.service.ServiceGroupDAO;
import com.erpanderp.wam.util.CommonLookup;
import com.erpanderp.wam.util.ValidationUtil;

@ManagedBean
@ViewScoped
public class CreateRoleBean implements Serializable {	
	private Map<String, String> roleTypes = CommonLookup.getRoleTypes();
	
	private String assignServiceGroupsAndServicesButtonLabel = CommonLookup.ASSIGN_SERVICEGROUP_SERVICE_LABEL;
	private boolean assignServiceGroupsAndServices;
	
	private List<Service> services = new ArrayList<Service>();
	private Service[] selectedServices;
	private Set<Service> assignedServicesSet = new HashSet<Service>();
	private List<Service> assignedServices = new ArrayList<Service>();
	private DataTable assignedServicesTable;
	private Service selectedService;
	
	private List<ServiceGroup> serviceGroups = new ArrayList<ServiceGroup>();
	private ServiceGroup[] selectedServiceGroups;
	private Set<ServiceGroup> assignedServiceGroupsSet = new HashSet<ServiceGroup>();
	private List<ServiceGroup> assignedServiceGroups = new ArrayList<ServiceGroup>();
	private DataTable assignedServiceGroupsTable;
	private ServiceGroup selectedServiceGroup;
	
	private boolean FORM_VALID;
	
	private Role role = new Role();
	
	RoleDAO roleDAO = new RoleDAO();
	ServiceDAO serviceDAO = new ServiceDAO();
	ServiceGroupDAO serviceGroupDAO = new ServiceGroupDAO();
		
	public CreateRoleBean(){
		
	}

	public void toggleAssignPanelDisplay(ActionEvent e){
		validate();
		if(FORM_VALID){
			System.out.println("Form Valid...");
			if(assignServiceGroupsAndServicesButtonLabel.equals(CommonLookup.ASSIGN_SERVICEGROUP_SERVICE_LABEL)){
				setAssignServiceGroupsAndServicesButtonLabel(CommonLookup.DO_NOT_ASSIGN_SERVICEGROUP_SERVICE_LABEL);
				setAssignServiceGroupsAndServices(true);
				services = serviceDAO.getAllServices();
				serviceGroups = serviceGroupDAO.getAllServiceGroups();
			}else{
				setAssignServiceGroupsAndServicesButtonLabel(CommonLookup.ASSIGN_SERVICEGROUP_SERVICE_LABEL);
				setAssignServiceGroupsAndServices(false);
				
				assignedServices.clear();
				assignedServicesSet.clear();
				services.clear();
				
				assignedServiceGroups.clear();
				assignedServiceGroupsSet.clear();
				serviceGroups.clear();
			}	
		}else{
			setAssignServiceGroupsAndServicesButtonLabel(CommonLookup.ASSIGN_SERVICEGROUP_SERVICE_LABEL);
			setAssignServiceGroupsAndServices(false);
			
			assignedServices.clear();
			assignedServicesSet.clear();
			services.clear();
			
			assignedServiceGroups.clear();
			assignedServiceGroupsSet.clear();
			serviceGroups.clear();
		}				
	}
	
	public void assignService(ActionEvent e){		
		assignedServicesSet.addAll( new ArrayList<Service>(Arrays.asList(selectedServices)));
		assignedServices.clear();
		assignedServices.addAll(assignedServicesSet);	
	}
	
	public void removeService(ActionEvent e){
		selectedService = (Service) assignedServicesTable.getRowData();
		assignedServicesSet.remove(selectedService);
		assignedServices.remove(selectedService);			
	}
	
	public void assignServiceGroup(ActionEvent e){		
		assignedServiceGroupsSet.addAll( new ArrayList<ServiceGroup>(Arrays.asList(selectedServiceGroups)));
		assignedServiceGroups.clear();
		assignedServiceGroups.addAll(assignedServiceGroupsSet);	
	}
	
	public void removeServiceGroup(ActionEvent e){
		selectedServiceGroup = (ServiceGroup) assignedServiceGroupsTable.getRowData();
		assignedServiceGroupsSet.remove(selectedServiceGroup);
		assignedServiceGroups.remove(selectedServiceGroup);			
	}
	
	public String saveRole(){
		System.out.println("Saving Role...");
		validate();
		if(FORM_VALID){
			role.setCreateDate(new Date());
			role.setCreatedBy(CommonLookup.CREATEDBY_DEVELOPER_TEXT);
			role.setStatus(CommonLookup.STATUS_ACTIVE);	
			
			// Create Role Services for each assigned services...
			for (Service service : assignedServices) {
				RoleService roleService = new RoleService();
				roleService.setCreateDate(new Date());
				roleService.setCreatedBy(CommonLookup.CREATEDBY_DEVELOPER_TEXT);
				roleService.setStatus(CommonLookup.STATUS_ACTIVE);
				roleService.setService(service);
				role.getRoleServices().add(roleService);				
			}
			
			for (ServiceGroup serviceGroup : assignedServiceGroups) {
				RoleServiceGroup roleServiceGroup = new RoleServiceGroup();
				roleServiceGroup.setCreateDate(new Date());
				roleServiceGroup.setCreatedBy(CommonLookup.CREATEDBY_DEVELOPER_TEXT);
				roleServiceGroup.setStatus(CommonLookup.STATUS_ACTIVE);
				roleServiceGroup.setServiceGroup(serviceGroup);
				role.getRoleServiceGroups().add(roleServiceGroup);				
			}
			
			try{
				roleDAO.createRole(role);
				FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, role.getRole() + " role created successfully.", ""));
			}catch(Exception e){
				e.printStackTrace();
				FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, role.getRole() + " role was not created. Please try again.", e.getMessage()));
			}
			role = new Role();
			setAssignServiceGroupsAndServicesButtonLabel(CommonLookup.ASSIGN_SERVICEGROUP_SERVICE_LABEL);
			services.clear();
			assignedServices.clear();
			setAssignServiceGroupsAndServices(false);
		}else{
			
		}	
		return null;
	}
	
	public void validate(){
		FORM_VALID = true;		
		
		if(ValidationUtil.isEmpty(role.getRole(), "Role Name", "roleName", FacesContext.getCurrentInstance()) != null){
			FORM_VALID = false;
		}else if(!roleDAO.isRoleAvailable(role.getRole())){
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Role is not available", ""));
			FORM_VALID = false;
		}
		
		if(ValidationUtil.isEmpty(role.getDisplayName(), "Display Name", "displayName", FacesContext.getCurrentInstance()) != null){
			System.out.println("Display Name is empty.");
			FORM_VALID = false;
		}else if(!roleDAO.isRoleDisplayNameAvailable(role.getDisplayName())){
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Display Name is not available", ""));
			FORM_VALID = false;
		}
	}
	
	public Map<String, String> getRoleTypes() {
		return roleTypes;
	}

	public void setRoleTypes(Map<String, String> roleTypes) {
		this.roleTypes = roleTypes;
	}

	public boolean isAssignServiceGroupsAndServices() {
		return assignServiceGroupsAndServices;
	}

	public void setAssignServiceGroupsAndServices(
			boolean assignServiceGroupsAndServices) {
		this.assignServiceGroupsAndServices = assignServiceGroupsAndServices;
	}

	public String getAssignServiceGroupsAndServicesButtonLabel() {
		return assignServiceGroupsAndServicesButtonLabel;
	}

	public void setAssignServiceGroupsAndServicesButtonLabel(
			String assignServiceGroupsAndServicesButtonlabel) {
		this.assignServiceGroupsAndServicesButtonLabel = assignServiceGroupsAndServicesButtonlabel;
	}

	public Role getRole() {
		return role;
	}

	public void setRole(Role role) {
		this.role = role;
	}

	public boolean isFORM_VALID() {
		return FORM_VALID;
	}

	public void setFORM_VALID(boolean fORM_VALID) {
		FORM_VALID = fORM_VALID;
	}

	public List<Service> getServices() {
		return services;
	}

	public void setServices(List<Service> services) {
		this.services = services;
	}

	public Service[] getSelectedServices() {
		return selectedServices;
	}

	public void setSelectedServices(Service[] selectedServices) {
		this.selectedServices = selectedServices;
	}

	public List<Service> getAssignedServices() {
		return assignedServices;
	}

	public void setAssignedServices(List<Service> assignedServices) {
		this.assignedServices = assignedServices;
	}

	public DataTable getAssignedServicesTable() {
		return assignedServicesTable;
	}

	public void setAssignedServicesTable(DataTable assignedServicesTable) {
		this.assignedServicesTable = assignedServicesTable;
	}

	public Service getSelectedService() {
		return selectedService;
	}

	public void setSelectedService(Service selectedService) {
		this.selectedService = selectedService;
	}

	public Set<Service> getAssignedServicesSet() {
		return assignedServicesSet;
	}

	public void setAssignedServicesSet(Set<Service> assignedServicesSet) {
		this.assignedServicesSet = assignedServicesSet;
	}

	public List<ServiceGroup> getServiceGroups() {
		return serviceGroups;
	}

	public void setServiceGroups(List<ServiceGroup> serviceGroups) {
		this.serviceGroups = serviceGroups;
	}

	public ServiceGroup[] getSelectedServiceGroups() {
		return selectedServiceGroups;
	}

	public void setSelectedServiceGroups(ServiceGroup[] selectedServiceGroups) {
		this.selectedServiceGroups = selectedServiceGroups;
	}

	public Set<ServiceGroup> getAssignedServiceGroupsSet() {
		return assignedServiceGroupsSet;
	}

	public void setAssignedServiceGroupsSet(Set<ServiceGroup> assignedServiceGroupsSet) {
		this.assignedServiceGroupsSet = assignedServiceGroupsSet;
	}

	public List<ServiceGroup> getAssignedServiceGroups() {
		return assignedServiceGroups;
	}

	public void setAssignedServiceGroups(List<ServiceGroup> assignedServiceGroups) {
		this.assignedServiceGroups = assignedServiceGroups;
	}

	public DataTable getAssignedServiceGroupsTable() {
		return assignedServiceGroupsTable;
	}

	public void setAssignedServiceGroupsTable(DataTable assignedServiceGroupsTable) {
		this.assignedServiceGroupsTable = assignedServiceGroupsTable;
	}

	public ServiceGroup getSelectedServiceGroup() {
		return selectedServiceGroup;
	}

	public void setSelectedServiceGroup(ServiceGroup selectedServiceGroup) {
		this.selectedServiceGroup = selectedServiceGroup;
	}
}
